﻿using System;
using System.Collections;
using System.IO;
using System.Text;

namespace ZYCommon
{
   

    public abstract class ObjectByteList : ArrayList
    {
        private bool bolEncryptString = true;
        protected bool bolFilterNullObject = false;
        private byte[] bytBuffer = new byte[100];
        private int intDataLength = 0;
        private int intForecastCount = 0;
        private Encoding myEncode = Encoding.UTF8;

        protected ObjectByteList()
        {
        }

        public void AppendBytes(byte[] bytData)
        {
            this.AppendBytes(bytData, 0, bytData.Length);
        }

        public void AppendBytes(byte[] bytData, int StartIndex, int Length)
        {
            if (((bytData != null) && (StartIndex >= 0)) && ((Length > 0) && ((StartIndex + Length) <= bytData.Length)))
            {
                lock (this)
                {
                    if ((this.intDataLength + Length) >= this.bytBuffer.Length)
                    {
                        byte[] buffer = new byte[(int) ((this.intDataLength + Length) * 1.5)];
                        for (int j = 0; j < this.bytBuffer.Length; j++)
                        {
                            buffer[j] = this.bytBuffer[j];
                        }
                        this.bytBuffer = buffer;
                    }
                    for (int i = 0; i < Length; i++)
                    {
                        this.bytBuffer[i + this.intDataLength] = bytData[i];
                    }
                    this.intDataLength += Length;
                }
            }
        }

        public void AppendObjectData(byte[] bytData)
        {
            if (bytData == null)
            {
                this.AppendBytes(BitConverter.GetBytes(0));
            }
            else
            {
                this.AppendBytes(BitConverter.GetBytes(bytData.Length));
                this.AppendBytes(bytData);
            }
        }

        public void AppendObjectData(int intData)
        {
            this.AppendBytes(BitConverter.GetBytes(intData));
        }

        public void AppendObjectData(string strData)
        {
            if (strData == null)
            {
                this.AppendBytes(BitConverter.GetBytes(0));
            }
            else
            {
                byte[] bytes = this.myEncode.GetBytes(strData);
                if (this.bolEncryptString)
                {
                    byte num = (byte) (bytes.Length & 0xff);
                    for (int i = 0; i < bytes.Length; i++)
                    {
                        bytes[i] = (byte) (bytes[i] ^ num);
                    }
                }
                this.AppendBytes(BitConverter.GetBytes(bytes.Length));
                this.AppendBytes(bytes);
            }
        }

        public virtual object BytesToObject(int ClassID)
        {
            return null;
        }

        public int Load(Stream myStream)
        {
            byte[] buffer = new byte[4];
            int classID = 0;
            int num3 = 0;
            if (myStream.CanRead && ((myStream.Read(buffer, 0, 4) != 4) || (this.DataHeadFlag != BitConverter.ToInt32(buffer, 0))))
            {
                throw new Exception("文件格式不对");
            }
            if (myStream.CanRead)
            {
                if (myStream.ReadByte() == 0)
                {
                    this.bolEncryptString = false;
                    this.myEncode = Encoding.GetEncoding(0x3a8);
                }
                else
                {
                    this.bolEncryptString = true;
                    this.myEncode = Encoding.UTF8;
                }
            }
            if (myStream.CanRead)
            {
                if (myStream.Read(buffer, 0, 4) != 4)
                {
                    return 0;
                }
                this.intForecastCount = BitConverter.ToInt32(buffer, 0);
                while (myStream.CanRead)
                {
                    if (myStream.Read(buffer, 0, 4) != 4)
                    {
                        break;
                    }
                    classID = BitConverter.ToInt32(buffer, 0);
                    if (classID == -1)
                    {
                        if (!this.bolFilterNullObject)
                        {
                            this.Add(null);
                            num3++;
                        }
                    }
                    else
                    {
                        if (myStream.Read(buffer, 0, 4) != 4)
                        {
                            break;
                        }
                        this.intDataLength = BitConverter.ToInt32(buffer, 0);
                        this.bytBuffer = new byte[this.intDataLength];
                        if (myStream.Read(this.bytBuffer, 0, this.intDataLength) != this.intDataLength)
                        {
                            break;
                        }
                        object obj2 = this.BytesToObject(classID);
                        if (this.bolFilterNullObject)
                        {
                            if (obj2 != null)
                            {
                                this.Add(obj2);
                                num3++;
                            }
                        }
                        else
                        {
                            this.Add(obj2);
                            num3++;
                        }
                    }
                }
            }
            else
            {
                return 0;
            }
            this.OnAfterLoad();
            return num3;
        }

        public int Load(string strFileName)
        {
            using (FileStream stream = new FileStream(strFileName, FileMode.Open, FileAccess.Read))
            {
                return this.Load(stream);
            }
        }

        public virtual bool ObjectToBytes(object objData, ref int ClassID)
        {
            return false;
        }

        public virtual void OnAfterLoad()
        {
        }

        public byte[] ReadBytes()
        {
            int length = this.ReadInt32();
            if (length <= 0)
            {
                return null;
            }
            return this.ReadBytes(length);
        }

        public byte[] ReadBytes(int Length)
        {
            lock (this)
            {
                if (this.intDataLength >= Length)
                {
                    byte[] buffer = new byte[Length];
                    for (int i = 0; i < Length; i++)
                    {
                        buffer[i] = this.bytBuffer[i];
                    }
                    for (int j = Length; j < this.intDataLength; j++)
                    {
                        this.bytBuffer[j - Length] = this.bytBuffer[j];
                    }
                    this.intDataLength -= Length;
                    return buffer;
                }
            }
            return null;
        }

        public int ReadInt32()
        {
            byte[] buffer = this.ReadBytes(4);
            if (buffer != null)
            {
                return BitConverter.ToInt32(buffer, 0);
            }
            return -1;
        }

        public string ReadString()
        {
            byte[] buffer = this.ReadBytes(4);
            if (buffer != null)
            {
                int length = BitConverter.ToInt32(buffer, 0);
                if (length == 0)
                {
                    return null;
                }
                buffer = this.ReadBytes(length);
                if (buffer == null)
                {
                    return null;
                }
                if (this.bolEncryptString)
                {
                    byte num2 = (byte) (length & 0xff);
                    for (int i = 0; i < buffer.Length; i++)
                    {
                        buffer[i] = (byte) (buffer[i] ^ num2);
                    }
                }
                return this.myEncode.GetString(buffer);
            }
            return null;
        }

        public int Save(Stream myStream)
        {
            int num = 0;
            int classID = 0;
            myStream.Write(BitConverter.GetBytes(this.DataHeadFlag), 0, 4);
            myStream.WriteByte(this.bolEncryptString ? ((byte) 1) : ((byte) 0));
            myStream.Write(BitConverter.GetBytes(this.Count), 0, 4);
            if (this.bolEncryptString)
            {
                this.myEncode = Encoding.UTF8;
            }
            else
            {
                this.myEncode = Encoding.GetEncoding(0x3a8);
            }
            foreach (object obj2 in this)
            {
                this.intDataLength = 0;
                if (this.ObjectToBytes(obj2, ref classID) && (this.intDataLength > 0))
                {
                    myStream.Write(BitConverter.GetBytes(classID), 0, 4);
                    myStream.Write(BitConverter.GetBytes(this.intDataLength), 0, 4);
                    myStream.Write(this.bytBuffer, 0, this.intDataLength);
                    num += this.intDataLength;
                }
                else if (!this.bolFilterNullObject)
                {
                    myStream.Write(BitConverter.GetBytes(-1), 0, 4);
                }
            }
            return num;
        }

        public int Save(string strFileName)
        {
            FileStream myStream = null;
            int num2;
            int num = 0;
            try
            {
                myStream = new FileStream(strFileName, FileMode.Create, FileAccess.Write);
                num = this.Save(myStream);
                myStream.Close();
                num2 = num;
            }
            catch (Exception exception)
            {
                if (myStream != null)
                {
                    myStream.Close();
                }
                throw exception;
            }
            return num2;
        }

        public virtual int DataHeadFlag
        {
            get
            {
                return 0x16079;
            }
        }

        public bool EncryptString
        {
            get
            {
                return this.bolEncryptString;
            }
            set
            {
                this.bolEncryptString = value;
            }
        }

        public bool FilterNullObject
        {
            get
            {
                return this.bolFilterNullObject;
            }
            set
            {
                this.bolFilterNullObject = value;
            }
        }

        public int ForecastCount
        {
            get
            {
                return this.intForecastCount;
            }
        }
    }
}

